﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.OleDb;
using System.Data;
using umbraco.uicontrols;
using umbraco.BasePages;


namespace Our.Umbraco.uDbCompare
{
    public partial class index : System.Web.UI.Page
    {
        private string GetSessionName(string paritalSessionName)
        {
            return string.Format("dbcompare_{0}_{1}", paritalSessionName, SessionVars.NodeId);
        }

        #region Properties

        private string username
        {
            get
            {
                string conn = Session[GetSessionName("username")] as string;
                return conn;

            }
            set 
            {
                Session[GetSessionName("username")] = value; 
            }
        }

        private string password
        {
            get
            {
                string conn = Session[GetSessionName("password")] as string;
                return conn;

            }
            set 
            {
                Session[GetSessionName("password")] = value; 
            }
        }

        private string compareOption
        {
            get
            {
                string option = Session[GetSessionName("option")] as string;
                return option;

            }
            set
            {
                Session[GetSessionName("option")] = value;
            }
        }


        private string compareLevel
        {
            get
            {
                string level = Session[GetSessionName("level")] as string;
                return level;

            }
            set
            {
                Session[GetSessionName("level")] = value;
            }
        }


        private DbCompareOptions CurrentOption
        {
            get { return (DbCompareOptions)Enum.Parse(typeof(DbCompareOptions), CompareOptionsDropDownList.SelectedValue); }
        }

        private DbCompareLevel CurrentLevel
        {
            get { return (DbCompareLevel)Enum.Parse(typeof(DbCompareLevel), CompareLevelDropDownList.SelectedValue); }
        }

        private Dictionary<DbCompareItem, string> DbCompareItemGridViewMapping
        {
            get
            {
                Dictionary<DbCompareItem, string> itemMapping = Session["dbcompare_itemmapping"] as Dictionary<DbCompareItem, string>;
                if (itemMapping == null)
                {
                    itemMapping = GetDbCompareItemGridViewMapping();
                    Session["dbcompare_itemmapping"] = itemMapping;
                }
                return itemMapping;
            }
        }

        private List<DbCompareItem> SelectedItems
        {
            get
            {
                return Session[GetSessionName("items")] as List<DbCompareItem>;
            }
            set
            {
                Session[GetSessionName("items")] = value;
            }
        }

        private Dictionary<DbCompareItem, DataTable> CachedTables
        {
            get
            {
                Dictionary<DbCompareItem, DataTable> cache = Session[GetSessionName("cachedTables")] as Dictionary<DbCompareItem, DataTable>;
                if (cache == null)
                    cache = new Dictionary<DbCompareItem, DataTable>();
                return cache;
            }
            set
            {
                Session[GetSessionName("cachedtables")] = value;
            }
        }

        private Dictionary<DbCompareItem, List<uDbCompareUI>> CachedUI
        {
            get
            {
                Dictionary<DbCompareItem, List<uDbCompareUI>> cache = Session[GetSessionName("cachedUI")] as Dictionary<DbCompareItem, List<uDbCompareUI>>;
                if (cache == null)
                    cache = new Dictionary<DbCompareItem, List<uDbCompareUI>>();
                return cache;
            }
            set
            {
                Session[GetSessionName("cachedUI")] = value;
            }
        }

        #endregion


        private Dictionary<DbCompareItem, string> GetDbCompareItemGridViewMapping()
        {
            var mapping = new Dictionary<DbCompareItem, string>();
            mapping.Add(DbCompareItem.DataType, "DataTypeGridView");
            mapping.Add(DbCompareItem.Dictionary, "DictionaryGridView");
            mapping.Add(DbCompareItem.DocTypeProperty, "DocTypePropertyGridView");
            mapping.Add(DbCompareItem.DocTypeStructure, "DocTypeStructureGridView");
            mapping.Add(DbCompareItem.DocTypeTemplate, "DocTypeTemplateGridView");
            mapping.Add(DbCompareItem.Macro, "MacroGridView");
            mapping.Add(DbCompareItem.MediaTypeProperty, "MediaTypePropertyGridView");
            mapping.Add(DbCompareItem.MediaTypeStructure, "MediaTypeStructureGridView");
            mapping.Add(DbCompareItem.MemberGroup, "MemberGroupGridView");
            mapping.Add(DbCompareItem.MemberType, "MemberTypeGridView");
            mapping.Add(DbCompareItem.Package, "PackageGridView");
            mapping.Add(DbCompareItem.RelationType, "RelationTypeGridView");
            mapping.Add(DbCompareItem.Template, "TemplateGridView");
            mapping.Add(DbCompareItem.Language, "LanguageGridView");
            return mapping;
        }

        public TabPage cacheTab;
        public TabPage compareTab;
        public TabPage settingsTab;
        public TabPage inUseTab;
        public ImageButton saveButtonData;

        #region Page Events

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            cacheTab = TabViewDetails.NewTabPage("Login");
            cacheTab.Controls.Add(CachePanel);

            compareTab = TabViewDetails.NewTabPage("Compare");
            compareTab.Controls.Add(MainPanel);

            inUseTab = TabViewDetails.NewTabPage("In Use");
            inUseTab.Controls.Add(InUsePanel);

            settingsTab = TabViewDetails.NewTabPage("Settings");
            settingsTab.Controls.Add(SettingsPanel);


            //Create a save button for the details tab.
            SetSaveButtonProperties("ImgBtnSaveDetails");

            CacheButton.Click += new EventHandler(CacheButton_Click);
            ClearCacheButton.Click += new EventHandler(ClearCacheButton_Click);
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
                BindData();
        }

        #endregion

        private void SetConnectionString()
        {
            SessionVars.CacheRemoteConnectionString(ConnectionStringTextBox.Text, UsernameTextBox.Text, PasswordTextBox.Text);
        }

        private void ClearConnectionString()
        {
            SessionVars.ClearCacheRemoteConnectionString();
        }

        /// <summary>
        /// Set the properites of the savebutton for a tab.
        /// </summary>
        /// <param name="saveButton"></param>
        /// <param name="id"></param>
        private void SetSaveButtonProperties(string id)
        {
            //Create a save button from the current datatab.
            saveButtonData = settingsTab.Menu.NewImageButton();
            saveButtonData.ID = id;
            saveButtonData.Click += new ImageClickEventHandler(SaveButton_Click);
            saveButtonData.AlternateText = "Save";
            saveButtonData.ValidationGroup = "Save";
            saveButtonData.ImageUrl = "~/umbraco/images/editor/save.gif";
        }



        protected void BindData()
        {
            CompareOptionsDropDownList.DataSource = Enum.GetNames(typeof(DbCompareOptions));
            CompareOptionsDropDownList.DataBind();
            if (!string.IsNullOrEmpty(compareOption))
                CompareOptionsDropDownList.SelectedValue = compareOption;

            CompareLevelDropDownList.DataSource = Enum.GetNames(typeof(DbCompareLevel));
            CompareLevelDropDownList.DataBind();
            if (!string.IsNullOrEmpty(compareLevel))
                CompareLevelDropDownList.SelectedValue = compareLevel;

            CompareItemsCheckBoxList.DataSource = Enum.GetNames(typeof(DbCompareItem));
            CompareItemsCheckBoxList.DataBind();
            if (SelectedItems != null && SelectedItems.Count > 0)
            {
                foreach (ListItem listItem in CompareItemsCheckBoxList.Items)
                {
                    DbCompareItem compareItem = (DbCompareItem)Enum.Parse(typeof(DbCompareItem), listItem.Value);
                    if (SelectedItems.Contains(compareItem))
                        listItem.Selected = true;
                }
            }

            ResultsPanel.Visible = false;

            UsernameTextBox.Text = username;
            PasswordTextBox.Text = password;

            if (SessionVars.NodeId >= 0)
            {
                ConnectionNameTextBox.Text = uDbCompareCMSNode.GetConnectionName(SessionVars.NodeId);
                ConnectionStringTextBox.Text = uDbCompareCMSNode.GetConnectionString(SessionVars.NodeId);
                HrefTextBox.Text = uDbCompareCMSNode.GetHref(SessionVars.NodeId);
                SetConnectionString();
            }
            ServerLabel.Text = SessionVars.GetServerNameAndDb(true, "unknown");
            
            if (SessionVars.IsValidDbConnection(true))
            {
                CompareButton.Enabled = true;
                CompareButton.Text = "Compare";

                LoginMultiView.SetActiveView(LogoutView);
            }
            else
            {
                CompareButton.Enabled = false;
                CompareButton.Text = "Account details need caching";

                LoginMultiView.SetActiveView(LoginView);
            }

            // If we're allowed to compare and there are session variables for CompareOption & CompareLevel
            // then go ahead and compare
            if (CompareButton.Enabled && 
                    !string.IsNullOrEmpty(compareOption) && 
                    !string.IsNullOrEmpty(compareLevel) &&
                    SessionVars.GetServerNameAndDb(true, "unknown") != "unknown")
            {
                PopulateAllGrids();
            }

            MacroInUse1.BindData();
            TemplateInUse1.BindData();
            DocTypeInUse1.BindData();
            LegacyAlias1.BindData();
            HiddenTabs1.BindData();
            TrailingSpace1.BindData();
            OrphanedDocTemplates1.BindData();
        }

        private void PopulateAllGrids()
        {
            ResultsPanel.Visible = true;

            foreach (ListItem listItem in CompareItemsCheckBoxList.Items)
            {
                DbCompareItem compareItem = (DbCompareItem)Enum.Parse(typeof(DbCompareItem), listItem.Value);

                System.Web.UI.HtmlControls.HtmlGenericControl div = ResultsPanel.FindControl(string.Format("{0}Div", compareItem)) as System.Web.UI.HtmlControls.HtmlGenericControl;
                div.Visible = listItem.Selected;

                if (listItem.Selected)
                {
                    PopulateGridView(compareItem);
                }
            }
        }

        #region Buttons

        protected void CacheButton_Click(object sender, EventArgs e)
        {
            username = UsernameTextBox.Text;
            password = PasswordTextBox.Text;

            SetConnectionString();
            BindData();

            if (SessionVars.IsValidDbConnection(true))
            {
                LoginLiteral.Text = string.Empty;
            }
            else
            {
                LoginLiteral.Text = "<br /><br /><font color='red'>Unable to login to db.  Please make sure your connection string is correct under the settings tab and that your user details are correct above.</font>";
            }
        }

        protected void SaveButton_Click(object sender, EventArgs e)
        {
            // Save connection string here`
            uDbCompareCMSNode.SaveConnectionName(SessionVars.NodeId, ConnectionNameTextBox.Text);
            uDbCompareCMSNode.SaveConnectionString(SessionVars.NodeId, ConnectionStringTextBox.Text);
            uDbCompareCMSNode.SaveHref(SessionVars.NodeId, HrefTextBox.Text);

            // Just in case someone sets integrated security, rebind, so that the correct login/logout control is shown
            BindData();

            var clientTools = new ClientTools(this.Page);
            
            clientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.save, "Connection Saved", "uDbCompare Connection has been saved");
        }

        protected void CompareButton_Click(object sender, EventArgs e)
        {
            // If we are comparing again, then destory the cache
            CachedTables = new Dictionary<DbCompareItem, DataTable>();

            PopulateAllGrids();

            compareLevel = CompareLevelDropDownList.SelectedValue;
            compareOption = CompareOptionsDropDownList.SelectedValue;

            SelectedItems = new List<DbCompareItem>();
            foreach (ListItem listItem in CompareItemsCheckBoxList.Items)
            {
                DbCompareItem compareItem = (DbCompareItem)Enum.Parse(typeof(DbCompareItem), listItem.Value);
                if (listItem.Selected)
                    SelectedItems.Add(compareItem);
            }            
        }

        protected void CheckAllButton_Click(object sender, EventArgs e)
        {
            foreach (ListItem listItem in CompareItemsCheckBoxList.Items)
            {
                listItem.Selected = true;
            }
        }

        protected void UncheckAllButton_Click(object sender, EventArgs e)
        {
            foreach (ListItem listItem in CompareItemsCheckBoxList.Items)
            {
                listItem.Selected = false;
            }
        }

        protected void ClearCacheButton_Click(object sender, EventArgs e)
        {
            username = string.Empty;
            password = string.Empty;
            ClearConnectionString();
            BindData();
        }

        #endregion

        #region GridViews

        private void PopulateGridView(DbCompareItem compareItem)
        {
            GridView gridView = ResultsPanel.FindControl(DbCompareItemGridViewMapping[compareItem]) as GridView;
            PopulateGridView(gridView, compareItem);
        }

        private void PopulateGridView(GridView gridView, DbCompareItem compareItem)
        {
            // if switching from difference to full, the number of columns could change...
            gridView.Columns.Clear();

            /*
            DataTable dt = null;
            if (CachedTables.ContainsKey(compareItem))
                dt = CachedTables[compareItem];

            if (dt == null)
            {
                dt = uDbCompare.Compare(compareItem, CurrentOption, CurrentLevel, SessionVars.CurrentConnectionString, SessionVars.RemoteConnectionString);
                CachedTables.Add(compareItem, dt);
            }
            */
            List<uDbCompareUI> compareList = null;
            if (CachedUI.ContainsKey(compareItem))
                compareList = CachedUI[compareItem];
            if (compareList == null)
            {
                compareList = uDbCompare.Compare(compareItem, CurrentOption, CurrentLevel, SessionVars.CurrentConnectionString, SessionVars.RemoteConnectionString);
                CachedUI.Add(compareItem, compareList);
            }

            if (gridView.Columns.Count == 0)
            {
                HyperLinkField link = new HyperLinkField();
                link.DataTextField = "Name";
                link.DataNavigateUrlFields = new string[] {"Name"};
                link.DataNavigateUrlFormatString = string.Format("detail.aspx?id={0}&CompareItem={1}&name=", SessionVars.NodeId, compareItem) + "{0}";
                link.HeaderText = "Name";
                gridView.Columns.Add(link);

                var leftField = new BoundField();
                leftField.DataField = "LeftData";
                leftField.HeaderText = SessionVars.GetServerNameAndDb(false, "Current Server");
                gridView.Columns.Add(leftField);

                var rightField = new BoundField();
                rightField.DataField = "RightData";
                rightField.HeaderText = SessionVars.GetServerNameAndDb(true, "Remote Server");
                gridView.Columns.Add(rightField);

            }

            //if (dt.Rows.Count > 0)
            if (compareList.Count > 0)
            {
                gridView.RowDataBound += new GridViewRowEventHandler(gridView_RowDataBound);

                gridView.DataSource = compareList;
                gridView.DataBind();

            }
            else
            {
                var dt = new DataTable();
                dt.Columns.Add(new DataColumn("NoDataPresent", typeof(string)));
                DataRow dr = dt.NewRow();
                dr["NoDataPresent"] = "No data is present - either all fields match or there is no data";
                dt.Rows.Add(dr);
                
                gridView.Columns.Clear();
                BoundField field = new BoundField();
                field.HeaderText = "No Data Present";
                field.DataField = "NoDataPresent";
                gridView.Columns.Add(field);
                gridView.DataSource = dt;
                gridView.DataBind();
                
            }

        }

        protected void gridView_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                uDbCompareUI compare = e.Row.DataItem as uDbCompareUI;

                compare.SetLeftCell(e.Row.Cells[1]);
                compare.SetRightCell(e.Row.Cells[2]);
                /*
                DataRowView drv = e.Row.DataItem as DataRowView;
                if (drv != null)
                {
                    // Old style table with name, left, & right
                    if (drv.Row.Table.Columns.Count == uDbCompare.CreateDataTable(LinkItem.Unknown).Columns.Count)
                    {
                        DbCompareMatch leftMatch = (DbCompareMatch)drv[uDbCompare.left];
                        DbCompareMatch rightMatch = (DbCompareMatch)drv[uDbCompare.right];
                        //e.Row.Cells[0].Text = drv[DbCompare.fieldName].ToString();
                        uDbCompareUI.SetCellColour(e.Row.Cells[1], leftMatch);
                        uDbCompareUI.SetCellColour(e.Row.Cells[2], rightMatch);
                    }
                    else
                    {
                        DbCompareMatch leftMatch = (DbCompareMatch)drv[uDbCompare.leftMatch];
                        DbCompareMatch rightMatch = (DbCompareMatch)drv[uDbCompare.rightMatch];
                        //e.Row.Cells[0].Text = drv[DbCompare.fieldName].ToString();
                        uDbCompareUI.SetLinkCell(e.Row.Cells[1], drv[uDbCompare.left] as string, drv[uDbCompare.leftLink] as string);
                        uDbCompareUI.SetLinkCell(e.Row.Cells[2], drv[uDbCompare.right] as string, drv[uDbCompare.rightLink] as string);
                        uDbCompareUI.SetCellColour(e.Row.Cells[1], leftMatch);
                        uDbCompareUI.SetCellColour(e.Row.Cells[2], rightMatch);
                    }
                }
                 */
            }
        }



        #endregion

    }
}
